﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Runtime.Serialization;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Xml;

using FluentBinding.WinForms.Convertors;
using FluentBinding.WinForms.Domain;

namespace FluentBinding.WinForms.Demo
{
    public partial class CustomerEntryForm : Form
    {
        Countries _countries = new Countries();
        Customer _customer = new Customer { Name = "New" };        

        public CustomerEntryForm()
        {
            InitializeComponent();

            SetupFluentBindings();
            //SetupClassicBinding();

            ThreadPool.QueueUserWorkItem(UpdateCustomerCreatedAt);
        }

        private void SubmitClicked(object sender, EventArgs e)
        {
            using(StringWriter writer = new StringWriter())
            using(XmlTextWriter xmlWriter = new XmlTextWriter(writer)) 
            {
                xmlWriter.Formatting = Formatting.Indented;

                new DataContractSerializer(typeof(Customer)).WriteObject(xmlWriter, _customer);

                MessageBox.Show(writer.ToString(), "Serialized Customer");
            }
        }

        private void SetupFluentBindings()
        {
            var bindings = new Bindings<Customer>(_customer);            

            bindings.Bind(_nameBox)
                .Text
                .To(x => x.Name, (x, value) => x.Name = value)
                .WithDataSourceUpdateMode(DataSourceUpdateMode.OnPropertyChanged);

            bindings.Bind(_firstNameBox).Text
                .To(x => x.FirstName)
                .WithNotifier(x => x, x => x.FirstName);

            bindings.Bind(_secondNameBox).Text
                .To(x => x.SecondName)
                .WithNotifier(x => x, x => x.SecondName);

            bindings.Bind(_birthDatePicker).Value
                .To(x => x.DateOfBirth, (x, value) => x.DateOfBirth = value);

            bindings.Bind(_countryComboBox).SelectedItem<Country>()
                .To(x => x.Country, (x, value) => x.Country = value)
                .WithDataSource(x => _countries.All, c => c.Name, "Select")
                .WithDataSourceUpdateMode(DataSourceUpdateMode.OnPropertyChanged)
                .WithAffectedBinding(x => x.Country);

            bindings.Bind(_countryCodeBox).Text
                .To(x => x.Country == null ? string.Empty : x.Country.Code)
                .WithEntityPath(x => x.Country);

            bindings.Bind(_createdAtLabel).Text
                .To(x => x.CreatedAt.ToString("yyyy.MM.dd HH:mm:ss"))
                .WithNotifier(x => x, c => c.CreatedAt);
        }

        private void SetupClassicBinding()
        {
            _customer.Country = _countries.Australia;

            _countryComboBox.DataSource = _countries.All.ToList();
            _countryComboBox.DisplayMember = "Name";
            _countryComboBox.DataBindings.Add("SelectedItem", _customer, "Country");
            
            //_nameBox.DataBindings.Add("Text", _customer, "Age");

            _countryCodeBox.DataBindings.Add("Text", _customer, "Country.City.Name");

            //_nameBox.DataBindings.Add(
            //    new Binding("Text", _customer, "Name", false, DataSourceUpdateMode.OnPropertyChanged));
        }

        /// <summary>
        /// Emulate updating entity from background thread
        /// </summary>
        private void UpdateCustomerCreatedAt(object state)
        {
            while(true)
            {
                Thread.Sleep(1000);

                _customer.CreatedAt = DateTime.Now;
            }
        }
    }
}
